package com.kly.user.serviceImpl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.fqgj.common.api.Response;
import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.common.utils.StringUtils;
import com.kly.enums.ParameterTypeEnum;
import com.kly.user.constant.RedisKey;
import com.kly.user.db.dao.*;
import com.kly.user.db.entity.*;
import com.kly.user.dto.TrafficSourceDto;
import com.kly.user.dto.UserAccessDto;
import com.kly.user.dto.UserBaseDto;
import com.kly.user.dto.UserLoginDto;
import com.kly.user.dto.chatter.request.ConversationReq;
import com.kly.user.dto.vo.TrafficSourceReq;
import com.kly.user.enums.*;
import com.kly.user.eventbus.ActionEnum;
import com.kly.user.eventbus.Event;
import com.kly.user.mapper.UserAccessMapper;
import com.kly.user.mapper.UserMapper;
import com.kly.user.msgClient.MsgAPI;
import com.kly.user.service.AuthLoginService;
import com.kly.user.service.UserConversationService;
import com.kly.user.service.UserTrafficSourceService;
import com.kly.user.service.WhiteListService;
import com.kly.user.utils.RedisService;
import com.kly.user.utils.ServiceUtils;
import com.kly.user.utils.UserSnowflake;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

@Slf4j
@Service("authLoginService")
public class AuthLoginServiceImpl implements AuthLoginService {

    @Resource
    UserAccessMapper userAccessMapper;
    @Resource
    UserMapper userMapper;
    @Resource
    UserAccountsDao userAccountsDao;
    @Resource
    UserAccessDao userAccessDao;
    @Resource
    UserDao userDao;
    @Resource
    UserAccessRongcloudDao userAccessRongcloudDao;
    @NacosValue(value = "${app.version.no:30}", autoRefreshed = true)
    private Integer appVersionNo;
    @Resource
    MsgAPI msgAPI;
    @NacosValue(value = "${meboo.white.list}", autoRefreshed = true)
    private String mebboWhiteList;
    @NacosValue(value = "${pp.white.list}", autoRefreshed = true)
    private String ppWhiteList;
    @Resource
    UserMsgSendTotalDao userMsgSendTotalDao;

    @Resource
    RedisService redisService;
    @Resource
    WhiteListService whiteListService;
    @Resource
    CustomersDao customersDao;
    @Resource
    CustomersUserDao customersUserDao;
    @Resource
    UserTrafficSourceService trafficSourceService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response<UserBaseDto> authLogin(UserLoginDto userLogin) {

        // 手机号码处理
        String mobile = userLogin.getMobile();
//        if (!AppCodeEnum.MEBOO.getAppCode().equals(userLogin.getAppCode())) {
//            if (StringUtils.isNotEmpty(userLogin.getMobile())) {
//                mobile = mobile.replace("+", "");
//                userLogin.setMobile(mobile);
//                userLogin.setAccount(mobile);
//            }
//        }

        UserAccountsEntity userAccounts = getUserAccounts(userLogin);

        // 指定用户注册时需要清白名单除缓存
        final Response<Boolean> resp = whiteListService.in(userLogin.getAppCode(), null, userLogin.getMobile(), userLogin.getEmail());
        Boolean whiteUserFlag = Boolean.FALSE;
        if (resp != null && resp.getData()) {
            redisService.del(RedisKey.USER_WHITE_LIST);
            redisService.del(RedisKey.USER_WHITE_LIST_VERSION);
            whiteUserFlag = Boolean.TRUE;
        }

        final CustomersEntity customer = customersDao.getCustomer(userLogin.getMobile(), userLogin.getEmail(), userLogin.getGoogleAdId());
        // 次首注册逻辑
        final Boolean firstRegister = userDao.isFirstRegister(userLogin.getClientId(), userLogin.getMobile(), userLogin.getEmail(), userLogin.getAppCode());

        // 判断账号是否存在
        if (userAccounts != null) {
            // 判断账号类型是否匹配
            if (Objects.equals(userAccounts.getAccountType(), userLogin.getLoginType())) {
                return processExistingUser(userAccounts, userLogin, customer, whiteUserFlag, firstRegister);
            } else {
                // 账号存在，但类型不匹配
                return Response.error(ResultStatus.INVALID_ACCOUNT_TYPE);
            }
        } else {
            // 账号不存在，进行初始化
            return initializeAccount(userLogin, customer, whiteUserFlag, firstRegister);
        }
    }

    // 获取用户账号
    private UserAccountsEntity getUserAccounts(UserLoginDto userLogin) {
        // 登陆方式为google, 版本号30以后客户端account改为email, 30版本之前为facebookId
        if (LoginType.GOOGLE.getType() == userLogin.getLoginType() && userLogin.getAppVersionNo() != null && userLogin.getAppVersionNo() >= appVersionNo) {
            Map<String, Object> accountParam = ServiceUtils.getParams();
            accountParam.put("account", userLogin.getAccount());
            accountParam.put("appCode", userLogin.getAppCode());
            return userAccountsDao.selectByAccountByEmail(accountParam);
        } else {
            Map<String, Object> accountParam = ServiceUtils.getParams();
            accountParam.put("account", userLogin.getAccount());
            accountParam.put("appCode", userLogin.getAppCode());
            return userAccountsDao.selectByAccount(accountParam);
        }

    }

    // 处理已存在的用户
    private Response<UserBaseDto> processExistingUser(UserAccountsEntity userAccounts, UserLoginDto userLogin,
                                                      CustomersEntity customer, Boolean whiteUserFlag, Boolean firstRegister) {
        UserEntity userEntity = userDao.selectByUserCode(userAccounts.getUserCode());

        // 获取用户来源

        if (userEntity == null) {
            // 如果不存在user则删除此account
            deleteUserAccount(userAccounts, userLogin);
            return initializeAccount(userLogin, customer, whiteUserFlag, firstRegister);
        }

        UserBaseDto userBaseDto = userMapper.UserToUserBase(userEntity);
        userBaseDto.setFirstRegister(firstRegister);
        userBaseDto.setNewUserFlag(userEntity.getGmtCreate().after(DateUtil.beginOfDay(new Date())));
        userBaseDto.setWhiteUserFlag(whiteUserFlag ? 1 : 0);
        userBaseDto.setTrafficSource(getTrafficSource(userEntity.getAppCode(), userEntity.getUserCode(), userEntity.getMobile(), userEntity.getEmail()).getType());
        return Response.ok(userBaseDto);
    }

    private TrafficSourceEnum getTrafficSource(String appCode, String userCode, String mobile, String email) {
        final TrafficSourceReq request = TrafficSourceReq.buildReq(appCode, userCode, mobile,email, null);
        final Response<TrafficSourceDto> trafficSourceDtoResponse = trafficSourceService.getTrafficSource(request);
        if (trafficSourceDtoResponse != null && trafficSourceDtoResponse.isSuccess()) {
            final TrafficSourceDto trafficSourceDto = trafficSourceDtoResponse.getData();
            if (trafficSourceDto != null) {
                return trafficSourceDto.getTrafficSourceEnum();
            }
        }
        return TrafficSourceEnum.All;
    }


    // 删除用户账号
    private void deleteUserAccount(UserAccountsEntity userAccounts, UserLoginDto userLogin) {
        Map<String, Object> params = ServiceUtils.getParams();
        params.put("userCode", userAccounts.getUserCode());
        params.put("accountType", userLogin.getLoginType());
        userAccountsDao.deleteByUserCode(params);
    }

    // 初始化账户
    private Response<UserBaseDto> initializeAccount(UserLoginDto userLogin, CustomersEntity customer, Boolean whiteUserFlag, Boolean firstRegister) {
        String userCode = String.valueOf(UserSnowflake.getInstance().nextId());
        String mobile = userLogin.getMobile();
        if (!AppCodeEnum.MEBOO.getAppCode().equals(userLogin.getAppCode())) {
            if (StringUtils.isNotEmpty(userLogin.getMobile())) {
                mobile = userLogin.getMobile().replace("+", "");
            }
        }

        UserEntity user = new UserEntity();
        user.setUserCode(userCode);
        user.setStatus(UserStatus.INIT.getType());
        user.setClientId(userLogin.getClientId());
        user.setUserType(UserType.NORMAL_USER.getType());
        user.setMobile(userLogin.getMobile());
        user.setMobile(mobile);
        user.setOnline(OnlineStatus.ONLINE_STATUS.getType());
        user.setEmail(userLogin.getEmail());
        user.setAppsFlyerUid(userLogin.getAppsFlyerUid());
        user.setCreateAt(new Date());
        user.setVersion(userLogin.getAppVersion());
        user.setChannel(userLogin.getChannel());
        user.setAppCode(userLogin.getAppCode());
        user.setAppSource(userLogin.getAppSource());
        userDao.insert(user);

        UserAccountsEntity userAccounts = new UserAccountsEntity();
        userAccounts.setUserCode(userCode);
        userAccounts.setAccountName(userLogin.getUserName());
        userAccounts.setAccount(userLogin.getAccount());
        userAccounts.setAccountType(userLogin.getLoginType());
        userAccounts.setIdentityToken(userLogin.getIdentityToken());
        userAccountsDao.insert(userAccounts);

        // 创建customer
        addCustomer(user.getUserCode(), user.getEmail(), mobile, customer);

        UserBaseDto userBaseDto = userMapper.UserToUserBase(user);

        userBaseDto.setFirstRegister(firstRegister);
        userBaseDto.setNewUserFlag(user.getGmtCreate().after(DateUtil.beginOfDay(new Date())));
        userBaseDto.setWhiteUserFlag(whiteUserFlag ? 1 : 0);
        userBaseDto.setTrafficSource(getTrafficSource(user.getAppCode(), user.getUserCode(), user.getMobile(), user.getEmail()).getType());
        return Response.ok(userBaseDto);
    }


    private void addCustomer(String userCode, String email, String mobile, CustomersEntity customer) {

        // 添加自然人
        if (customer == null) {
            final String customerCode = String.valueOf(UserSnowflake.getInstance().nextId());
            customer = customersDao.addCustomer(customerCode, email, mobile, null, null);
        }

        // 添加自然人映射信息
        CustomersUserEntity customersUser = customersUserDao.getCustomer(userCode);
        if (customersUser == null) {
            customersUserDao.addCustomersUser(customer.getCustomerCode(), userCode);
        }

    }


    /**
     * 新逻辑，处理客户和用户关系的
     */
    private void createCustomer() {

    }

    @Override
    public Response<String> logout(String userCode) {
        // 删除token信息
        int i = userAccessDao.deleteByUserCode(userCode);
        userDao.delete(userCode);

        // 用户发送消息记录
        final List<UserMsgSendTotalEntity> userMsgSendTotalEntities = userMsgSendTotalDao.queryByUserCode(userCode, null);
        if (CollectionUtils.isEmpty(userMsgSendTotalEntities)) {
            return Response.ok(String.valueOf(i));
        }

        // 删除会话列表
        for (UserMsgSendTotalEntity entity : userMsgSendTotalEntities) {
            Map<String, Object> params = new HashMap<>();
            params.put("type", ParameterTypeEnum.MESSAGE_FEEDBACK.getId());
            params.put("bizCode", "M20005");
            params.put("userCode", userCode);
            params.put("modelUserCode", entity.getToUserCode());
            msgAPI.userLogOut(userCode, entity.getToUserCode(), entity.getChatterUserCode());
        }

        return Response.ok(String.valueOf(i));
    }


    @Override
    public Response<String> getToKen(String userCode, UserTokenType userTokenType) {
        Map<String, Object> map = ServiceUtils.getParams();
        map.put("userCode", userCode);
        map.put("bizType", userTokenType.getCode());
        List<UserAccessEntity> userAccessEntities = userAccessDao.selectByParams(map);
        String token = Optional.ofNullable(userAccessEntities)
                .filter(list -> !list.isEmpty())
                .map(list -> list.get(0).getToken())
                .orElse(null);
        return Response.ok(token);
    }

    @Override
    public Response<String> saveToken(UserAccessDto userAccessDto, UserTokenType userTokenType) {
        UserAccessEntity accessEntity;
        Map<String, Object> map = ServiceUtils.getParams();
        map.put("userCode", userAccessDto.getUserCode());
        map.put("bizType", userTokenType.getCode());
        List<UserAccessEntity> userAccessEntities = userAccessDao.selectByParams(map);
        if (userAccessEntities != null && !userAccessEntities.isEmpty()) {
            accessEntity = userAccessEntities.get(0);
            accessEntity.setToken(userAccessDto.getToken());
            userAccessDao.updateByPrimaryKey(accessEntity);
        } else {
            accessEntity = userAccessMapper.toEntity(userAccessDto);
            accessEntity.setBizType(userTokenType.getCode());
            userAccessDao.insert(accessEntity);
        }
        return Response.ok();

    }

    @Override
    public Response<String> getRongCloudToken(String userCode) {
        Map<String, Object> map = ServiceUtils.getParams();
        map.put("userCode", userCode);
        List<UserAccessRongcloudEntity> userAccessRongclouds = userAccessRongcloudDao.selectByParams(map);
        String token = Optional.ofNullable(userAccessRongclouds)
                .filter(list -> !list.isEmpty())
                .map(list -> list.get(0).getToken())
                .orElse(null);
        return Response.ok(token, "success");
    }

    @Override
    public Response<String> saveRongCloudToken(UserAccessDto userAccessDto) {
        Map<String, Object> map = ServiceUtils.getParams();
        map.put("userCode", userAccessDto.getUserCode());
        List<UserAccessRongcloudEntity> userAccessRongclouds = userAccessRongcloudDao.selectByParams(map);
        UserAccessRongcloudEntity userAccessRongcloud;
        if (userAccessRongclouds != null && !userAccessRongclouds.isEmpty()) {
            userAccessRongcloud = userAccessRongclouds.get(0);
            userAccessRongcloud.setToken(userAccessDto.getToken());
            userAccessRongcloudDao.updateByPrimaryKey(userAccessRongcloud);
        } else {
            userAccessRongcloud = userAccessMapper.toRongCloudEntity(userAccessDto);
            userAccessRongcloudDao.insert(userAccessRongcloud);
        }
        return Response.ok();
    }

    /**
     * 返回用户同一设备多次注册的第一个有效账户信息
     * 条件：通过设备id/mobile/email去认定是否为同一用户
     */
    @Override
    public Response<Boolean> firstRegister(String clientId, String mobile, String email, String appCode) {
        return Response.ok(userDao.isFirstRegister(clientId, mobile, email, appCode));
    }

    @Override
    public Response<Boolean> firstRegister(String userCode, String appCode) {
        final UserEntity user = userDao.selectByUserCode(userCode);
        if (user == null) {
            return Response.ok(Boolean.TRUE);
        }
        return Response.ok(userDao.isFirstRegister(user.getClientId(), user.getMobile(), user.getEmail(), appCode));
    }


}
